package domain;

import Technical.DatabaseHandler;
import gui2.outputInterface;
import java.util.ArrayList;
import java.util.Random;

public class MonteCarlo
{

    private outputInterface out;
    private ArrayList<MCState> movesMade;
    private int player;
    private Random rand;

    public MonteCarlo(outputInterface outInterface, int player)
    {
        this.out = outInterface;
        this.player = player;
        movesMade = new ArrayList<>();
        rand = new Random();
    }

    public void evaluateGame(GameGrid g)
    {
        int moveSize = movesMade.size();
        double result = 0;

        if (g.GetWinner() == 0) {
            result = -100.00;
        } else if (g.GetWinner() == player) {
            result = g.getCount(player);
        } else {
            result = -g.getCount(player);
        }
        if(result == 0)
            result = -10000;

        for (int i = (movesMade.size() - 1); i >= 0; i--) {
            if (player == 1) {
                //System.out.println("score: " + movesMade.get(i).getPlayer1Score() + " " + result);
                movesMade.get(i).setPlayer1score((movesMade.get(i).getPlayer1Score() + result));
                //System.out.println("p1: " + movesMade.get(i).getPlayer1Score());
                DatabaseHandler.getInstance().SaveState(movesMade.get(i));
            } else {
                //System.out.println("score: " + movesMade.get(i).getPlayer2Score() + " " + result);
                movesMade.get(i).setPlayer2score((movesMade.get(i).getPlayer2Score() + result));
                //System.out.println("p2: " + movesMade.get(i).getPlayer2Score());
                DatabaseHandler.getInstance().SaveState(movesMade.get(i));
            }
        }
    }

    // Det är här den aktuella griden skickas in!
    public Move getMove(GameGrid grid)
    {
        MCState bestState = null;

        ArrayList<MCState> possibleStates = getPossibleStates(player, grid);

        if (possibleStates.isEmpty()) {
            return null;
        }

        MCState tempState = null;
        for (int i = 0; i < possibleStates.size(); i++) {
            if (DatabaseHandler.getInstance().checkState(possibleStates.get(i))) {
                tempState = DatabaseHandler.getInstance().lookup(possibleStates.get(i));
                possibleStates.get(i).setPlayer1score(tempState.getPlayer1Score());
                possibleStates.get(i).setPlayer2score(tempState.getPlayer2Score());
            }
        }


        // Hämta ut det move som ger mest profit!
        bestState = possibleStates.get(0);
        for (int i = 0; i < possibleStates.size(); i++) {
            if (player == 1) {
                if (bestState.getPlayer1Score() < possibleStates.get(i).getPlayer1Score()) {
                    bestState = possibleStates.get(i);
                }
            } else {
                if (bestState.getPlayer2Score() < possibleStates.get(i).getPlayer2Score()) {
                    bestState = possibleStates.get(i);
                }
            }
        }

        int randNum;
        if (player == 1 && bestState.getPlayer1Score() < 0) {
            randNum = rand.nextInt(possibleStates.size());
            bestState = possibleStates.get(randNum);
            System.out.println("Making Random move. " + randNum);
        }

        if (player == 2 && bestState.getPlayer2Score() < 0) {
            randNum = rand.nextInt(possibleStates.size());
            bestState = possibleStates.get(randNum);
            System.out.println("Making Random move. " + randNum);
        }

        movesMade.add(bestState);

        return bestState.getMove();
    }

    public ArrayList<MCState> getPossibleStates(int player, GameGrid grid)
    {
        ArrayList<MCState> states = new ArrayList<>();
        GameGrid gridClone;

        for (int x = 0; x < 8; x++) {
            for (int y = 0; y < 8; y++) {
                if (grid.isLegalMove(player, x, y)) {
                    //gör draget x,y på brädet och flippa
                    gridClone = copyGrid(grid);
                    gridClone.makeMove(player, x, y);
                    states.add(new MCState(getState(x, y, player, gridClone), 0, 0, new Move(x, y)));
                }
            }
        }
        return states;
    }

    private byte[] getState(int mx, int my, int player, GameGrid grid)
    {
        byte[] state = new byte[64];
        int i = 0;
        for (int x = 0; x < 8; x++) {
            for (int y = 0; y < 8; y++) {
                if (x == mx && y == my) {
                    state[i] = (byte) player;
                } else {
                    state[i] = (byte) grid.GameGrid[x][y].getOwner();
                }
                i++;
            }
        }
        return state;
    }

    private GameGrid copyGrid(GameGrid gridOne)
    {
        GameGrid gridCopy = new GameGrid();

        for (int y = 0; y < 8; y++) {
            for (int x = 0; x < 8; x++) {
                if (gridOne.GameGrid[x][y].getOwner() == 1) {
                    gridCopy.GameGrid[x][y].setOwner(1);
                } else if (gridOne.GameGrid[x][y].getOwner() == 2) {
                    gridCopy.GameGrid[x][y].setOwner(2);
                } else if (gridOne.GameGrid[x][y].getOwner() == 0) {
                    gridCopy.GameGrid[x][y].setOwner(0);
                }

            }

        }
        return gridCopy;
    }
}
